package com.jboom.jboomconverter.processors;

import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.Elements;
import javax.tools.Diagnostic;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.Set;

import com.google.auto.service.AutoService;
import com.jboom.jboomconverter.annotation.ConvertMethod;
import com.jboom.jboomconverter.annotation.Converter;
import com.jboom.jboomconverter.util.ConverterGen;
import com.squareup.javapoet.JavaFile;

/**
 * @author zhangwen
 * @date 2023/5/27 19:42
 */
@AutoService(Processor.class) // 注解用于自动生成spi文件
@SupportedAnnotationTypes({
        "com.jboom.jboomconverter.annotation.ConvertMethod",
        "com.jboom.jboomconverter.annotation.Convert"
})
@SupportedSourceVersion(value = SourceVersion.RELEASE_8)
public class ConverterProcessor extends AbstractProcessor {

    /**
     * 写入文件
     */
    private Filer filer;

    private Elements elementUtil;

    private Messager messager;

    @Override
    public synchronized void init(ProcessingEnvironment processingEnv) {
        super.init(processingEnv);
        this.filer = processingEnv.getFiler();
        this.elementUtil = processingEnv.getElementUtils();
        this.messager = processingEnv.getMessager();
    }

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        if (annotations.isEmpty()) {
            return false;
        }
        parseElements(roundEnv, Converter.class);
        return true;
    }

    private void parseElements(RoundEnvironment roundEnv, Class<? extends Annotation> annotationClass) {
        Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(Converter.class);
        Set<? extends Element> methodElements = roundEnv.getElementsAnnotatedWith(ConvertMethod.class);
        ConverterGen.parseCustomizeConverter(methodElements);
        for (Element element : elements) {
            if (element.getKind() != ElementKind.INTERFACE) {
                // 目前只处理接口类型
                continue;
            }
            messager.printMessage(Diagnostic.Kind.NOTE, element.getSimpleName().toString());
            ConverterGen converterGen = new ConverterGen(elementUtil, messager);
            JavaFile javaFile = converterGen.genMapperImpl(element);
            try {
                // 生成类文件
                javaFile.writeTo(filer);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
